﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Phoenix.Xna.Framework.Components;
using Phoenix.Xna.Framework.Components.Compositors;
using Phoenix.Xna.Framework.ContentPipeline;
using Phoenix.Xna.Framework.Graphics;
using Phoenix.Xna.Framework.Input;
using Phoenix.Xna.Framework.MessagePipeline;
using Phoenix.Xna.Framework.Input.Binding;

namespace Phoenix.Xna.Framework
{
    public abstract class Engine : Game
    {
        private GraphicsDeviceManager _graphicsDeviceManager;
        private Vector2 _resolution = new Vector2(800, 600);

        public static Engine Instance { get; private set; }
        public new ServiceCollection Services { get; private set; }
        public ISettingsService SettingManager { get; private set; }
        public new IContentService Content { get; set; }
        public new ComponentCollection Components { get; private set; }
        public CompositorCollection Compositors { get; private set; }
        public new GraphicsDevice GraphicsDevice
        {
            get { return _graphicsDeviceManager.GraphicsDevice; }
        }
        public IMessageService MessageManager { get; private set; }
        public ISpriteBatchService SpriteManager { get; private set; }
        public bool IsFullScreen
        {
            get { return _graphicsDeviceManager.IsFullScreen; }
            set { _graphicsDeviceManager.IsFullScreen = value; }
        }
        public Vector2 Resolution
        {
            get { return _resolution; }
            set
            {
                if (value != _resolution)
                {
                    _resolution = value;
                    _graphicsDeviceManager.PreferredBackBufferWidth = (int)_resolution.X;
                    _graphicsDeviceManager.PreferredBackBufferHeight = (int)_resolution.Y;
                    _graphicsDeviceManager.ApplyChanges();
                }
            }
        }
        public FillMode FillMode
        {
            get { return GraphicsDevice.RenderState.FillMode; }
            set { GraphicsDevice.RenderState.FillMode = value; }
        }
        public Color FillColor { get; set; }

        public Engine()
        {
            Services = new ServiceCollection();
            //SettingManager = new SettingsService();
            InitializeGraphics();
            Content = new ContentService(this);
            Components = new ComponentCollection();
            Compositors = new CompositorCollection(this);
            //MessageManager = new MessageService();
            //MessageManager.Start();
            Instance = this;
        }

        private void InitializeGraphics()
        {
            _graphicsDeviceManager = new GraphicsDeviceManager(this);
            _graphicsDeviceManager.PreferMultiSampling = true;
            _graphicsDeviceManager.SynchronizeWithVerticalRetrace = false;
            _graphicsDeviceManager.PreferredBackBufferWidth = (int)_resolution.X;
            _graphicsDeviceManager.PreferredBackBufferHeight = (int)_resolution.Y;
            _graphicsDeviceManager.ApplyChanges();
            Services.AddService<IGraphicsDeviceManager>(_graphicsDeviceManager);
            Services.AddService<IGraphicsDeviceService>(_graphicsDeviceManager);
        }

        #region Game Members

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            SpriteManager = new SpriteBatchService();
            Compositors.SpriteBatch = Services.GetService<ISpriteBatchService>().SpriteBatch;
            base.LoadContent();
        }

        protected override void UnloadContent()
        {
            Components.Dispose();
            Compositors.Dispose();
            base.UnloadContent();
        }

        protected override void Update(GameTime gameTime)
        {
            InputManager.Instance.Update(gameTime);
            Components.Update(gameTime);
            Compositors.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            Components.Draw(gameTime);
            Compositors.Draw(gameTime);
        }

        #endregion
    }
}
